package cn.itcast.manus.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.itcast.manus.agent.AgentFactory;
import cn.itcast.manus.dto.DialogMessageDTO;
import cn.itcast.manus.enums.AgentTypeEnum;
import cn.itcast.manus.message.WSSessionManagement;
import cn.itcast.manus.service.WebSocketService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.stereotype.Service;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
@Service
@RequiredArgsConstructor
public class WebSocketServiceImpl implements WebSocketService {

    private final WSSessionManagement wsSessionManagement;
    private final ExecutorService executor = Executors.newCachedThreadPool();

    @Override
    public void enhancedDialog(DialogMessageDTO message, SimpMessageHeaderAccessor headerAccessor) {
        if(StrUtil.isEmpty(message.getText())){
            log.info("receive empty message!!!");
            return;
        }

        // 获取会话id
        var sessionId = headerAccessor.getSessionId();
        // 根据会话id获取对话对象
        var wsSession = this.wsSessionManagement.sessionDialog(sessionId);
        // 将消息对象写入到会话中
        wsSession.receiveMessages(message);

        //对客户端发送消息
        //wsSession.sendMessage("消息已收到！");

        // 通过智能体进行处理业务
        var agent = AgentFactory.getAgent(AgentTypeEnum.RE_ACT_PLANNING_AGENT).apply(wsSession);
        /**
         * 代码创建了一个 Runnable 实例（使用 Lambda 表达式简化语法），封装了与客户端交互的完整业务流程
         * 通过 executor.execute(src) 将任务提交到线程池执行，实现了请求的异步处理
         * 线程池是通过 Executors.newCachedThreadPool() 创建的可缓存线程池
         * 避免阻塞 WebSocket 连接
         *
         * WebSocket 作为一种长连接协议，需要保持连接的响应性
         * 智能体（Agent）处理任务可能耗时较长（如调用大模型、执行复杂规划等）
         * 使用 Runnable 异步执行可确保 WebSocket 连接不会被长时间运行的任务阻塞，从而能够处理更多并发请求
         * 技术设计优势
         * 提高系统吞吐量：通过线程池复用线程资源，避免频繁创建和销毁线程的开销
         * 增强用户体验：异步处理确保 WebSocket 连接始终保持响应状态，不会让用户感觉界面卡顿
         * 合理的资源隔离：将耗时的业务处理与 WebSocket 连接管理分离，便于系统维护和扩展
         * 错误隔离：单个任务的失败不会影响整个 WebSocket 服务的运行
         */
        Runnable src = () -> {
            try {
                // 获取客户端发来的消息
                var rawInput = wsSession.readMessage();
                // 通过规划agent进行执行
                var finalResult = agent.solveTask(rawInput);
                log.info("complete with final result:{}", finalResult);
                wsSession.sendMessage(finalResult);
                wsSession.sendMessage("任务流程结束");
            } finally {
                wsSessionManagement.clean(sessionId);
            }
        };
        executor.execute(src);
    }
}
